/*
 * TeleStax, Open Source Cloud Communications  Copyright 2012.
 * and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.mobicents.protocols.ss7.tools.simulator.tests.sms;

import org.apache.log4j.Level;
import org.mobicents.protocols.ss7.map.api.MAPApplicationContext;
import org.mobicents.protocols.ss7.map.api.MAPApplicationContextName;
import org.mobicents.protocols.ss7.map.api.MAPApplicationContextVersion;
import org.mobicents.protocols.ss7.map.api.MAPDialog;
import org.mobicents.protocols.ss7.map.api.MAPDialogListener;
import org.mobicents.protocols.ss7.map.api.MAPException;
import org.mobicents.protocols.ss7.map.api.MAPProvider;
import org.mobicents.protocols.ss7.map.api.errors.AbsentSubscriberDiagnosticSM;
import org.mobicents.protocols.ss7.map.api.errors.CallBarringCause;
import org.mobicents.protocols.ss7.map.api.errors.MAPErrorMessage;
import org.mobicents.protocols.ss7.map.api.errors.SMEnumeratedDeliveryFailureCause;
import org.mobicents.protocols.ss7.map.api.primitives.AddressNature;
import org.mobicents.protocols.ss7.map.api.primitives.AddressString;
import org.mobicents.protocols.ss7.map.api.primitives.IMSI;
import org.mobicents.protocols.ss7.map.api.primitives.ISDNAddressString;
import org.mobicents.protocols.ss7.map.api.primitives.LMSI;
import org.mobicents.protocols.ss7.map.api.primitives.MAPExtensionContainer;
import org.mobicents.protocols.ss7.map.api.primitives.NetworkResource;
import org.mobicents.protocols.ss7.map.api.primitives.NumberingPlan;
import org.mobicents.protocols.ss7.map.api.service.sms.AlertServiceCentreRequest;
import org.mobicents.protocols.ss7.map.api.service.sms.AlertServiceCentreResponse;
import org.mobicents.protocols.ss7.map.api.service.sms.ForwardShortMessageRequest;
import org.mobicents.protocols.ss7.map.api.service.sms.ForwardShortMessageResponse;
import org.mobicents.protocols.ss7.map.api.service.sms.InformServiceCentreRequest;
import org.mobicents.protocols.ss7.map.api.service.sms.LocationInfoWithLMSI;
import org.mobicents.protocols.ss7.map.api.service.sms.MAPDialogSms;
import org.mobicents.protocols.ss7.map.api.service.sms.MAPServiceSmsListener;
import org.mobicents.protocols.ss7.map.api.service.sms.MWStatus;
import org.mobicents.protocols.ss7.map.api.service.sms.MoForwardShortMessageRequest;
import org.mobicents.protocols.ss7.map.api.service.sms.MoForwardShortMessageResponse;
import org.mobicents.protocols.ss7.map.api.service.sms.MtForwardShortMessageRequest;
import org.mobicents.protocols.ss7.map.api.service.sms.MtForwardShortMessageResponse;
import org.mobicents.protocols.ss7.map.api.service.sms.ReportSMDeliveryStatusRequest;
import org.mobicents.protocols.ss7.map.api.service.sms.ReportSMDeliveryStatusResponse;
import org.mobicents.protocols.ss7.map.api.service.sms.SM_RP_DA;
import org.mobicents.protocols.ss7.map.api.service.sms.SM_RP_OA;
import org.mobicents.protocols.ss7.map.api.service.sms.SendRoutingInfoForSMRequest;
import org.mobicents.protocols.ss7.map.api.service.sms.SendRoutingInfoForSMResponse;
import org.mobicents.protocols.ss7.map.api.service.sms.SmsSignalInfo;
import org.mobicents.protocols.ss7.map.api.smstpdu.AddressField;
import org.mobicents.protocols.ss7.map.api.smstpdu.DataCodingScheme;
import org.mobicents.protocols.ss7.map.api.smstpdu.NumberingPlanIdentification;
import org.mobicents.protocols.ss7.map.api.smstpdu.ProtocolIdentifier;
import org.mobicents.protocols.ss7.map.api.smstpdu.SmsDeliverTpdu;
import org.mobicents.protocols.ss7.map.api.smstpdu.SmsSubmitTpdu;
import org.mobicents.protocols.ss7.map.api.smstpdu.SmsTpdu;
import org.mobicents.protocols.ss7.map.api.smstpdu.TypeOfNumber;
import org.mobicents.protocols.ss7.map.api.smstpdu.UserData;
import org.mobicents.protocols.ss7.map.api.smstpdu.ValidityPeriod;
import org.mobicents.protocols.ss7.map.smstpdu.AddressFieldImpl;
import org.mobicents.protocols.ss7.map.smstpdu.DataCodingSchemeImpl;
import org.mobicents.protocols.ss7.map.smstpdu.ProtocolIdentifierImpl;
import org.mobicents.protocols.ss7.map.smstpdu.SmsSubmitTpduImpl;
import org.mobicents.protocols.ss7.map.smstpdu.UserDataImpl;
import org.mobicents.protocols.ss7.map.smstpdu.ValidityPeriodImpl;
import org.mobicents.protocols.ss7.tcap.asn.comp.Problem;
import org.mobicents.protocols.ss7.tools.simulator.Stoppable;
import org.mobicents.protocols.ss7.tools.simulator.common.AddressNatureType;
import org.mobicents.protocols.ss7.tools.simulator.common.TesterBase;
import org.mobicents.protocols.ss7.tools.simulator.level3.MapMan;
import org.mobicents.protocols.ss7.tools.simulator.level3.MapProtocolVersion;
import org.mobicents.protocols.ss7.tools.simulator.level3.NumberingPlanMapType;
import org.mobicents.protocols.ss7.tools.simulator.management.TesterHost;

/**
 * 
 * @author sergey vetyutnev
 * 
 */
public class TestSmsClientMan extends TesterBase implements TestSmsClientManMBean, Stoppable, MAPDialogListener, MAPServiceSmsListener {

	public static String SOURCE_NAME = "TestSmsClient";

	private final String name;
	private MapMan mapMan;

	private boolean isStarted = false;
	private int countSriReq = 0;
	private int countSriResp = 0;
	private int countMtFsmReq = 0;
	private int countMtFsmResp = 0;
	private int countMoFsmReq = 0;
	private int countMoFsmResp = 0;
	private int countIscReq = 0;
	private int countRsmdsReq = 0;
	private int countRsmdsResp = 0;
	private int countAscReq = 0;
	private int countAscResp = 0;
	private int countErrRcvd = 0;
	private int countErrSent = 0;
	private String currentRequestDef = "";
	private boolean needSendSend = false;
	private boolean needSendClose = false;
	private int mesRef = 0;

	public TestSmsClientMan() {
		super(SOURCE_NAME);
		this.name = "???";
	}

	public TestSmsClientMan(String name) {
		super(SOURCE_NAME);
		this.name = name;
	}

	public void setTesterHost(TesterHost testerHost) {
		this.testerHost = testerHost;
	}

	public void setMapMan(MapMan val) {
		this.mapMan = val;
	}


	@Override
	public AddressNatureType getAddressNature() {
		return new AddressNatureType(this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getAddressNature().getIndicator());
	}

	@Override
	public String getAddressNature_Value() {
		return new AddressNatureType(this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getAddressNature().getIndicator()).toString();
	}

	@Override
	public void setAddressNature(AddressNatureType val) {
		this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().setAddressNature(AddressNature.getInstance(val.intValue()));
		this.testerHost.markStore();
	}

	@Override
	public NumberingPlanMapType getNumberingPlan() {
		return new NumberingPlanMapType(this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getNumberingPlan().getIndicator());
	}

	@Override
	public String getNumberingPlan_Value() {
		return new NumberingPlanMapType(this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getNumberingPlan().getIndicator()).toString();
	}

	@Override
	public void setNumberingPlan(NumberingPlanMapType val) {
		this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().setNumberingPlan(NumberingPlan.getInstance(val.intValue()));
		this.testerHost.markStore();
	}

	@Override
	public String getServiceCenterAddress() {
		return this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getServiceCenterAddress();
	}

	@Override
	public void setServiceCenterAddress(String val) {
		this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().setServiceCenterAddress(val);
		this.testerHost.markStore();
	}

	@Override
	public MapProtocolVersion getMapProtocolVersion() {
		return this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getMapProtocolVersion();
	}

	@Override
	public String getMapProtocolVersion_Value() {
		return this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getMapProtocolVersion().toString();
	}

	@Override
	public void setMapProtocolVersion(MapProtocolVersion val) {
		this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().setMapProtocolVersion(val);
		this.testerHost.markStore();
	}


	@Override
	public SRIReaction getSRIReaction() {
		return this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getSRIReaction();
	}

	@Override
	public String getSRIReaction_Value() {
		return this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getSRIReaction().toString();
	}

	@Override
	public void setSRIReaction(SRIReaction val) {
		this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().setSRIReaction(val);
		this.testerHost.markStore();
	}

	@Override
	public SRIInformServiceCenter getSRIInformServiceCenter() {
		return this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getSRIInformServiceCenter();
	}

	@Override
	public String getSRIInformServiceCenter_Value() {
		return this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getSRIInformServiceCenter().toString();
	}

	@Override
	public void setSRIInformServiceCenter(SRIInformServiceCenter val) {
		this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().setSRIInformServiceCenter(val);
		this.testerHost.markStore();
	}

	@Override
	public boolean isSRIScAddressNotIncluded() {
		return this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().isSRIScAddressNotIncluded();
	}

	@Override
	public void setSRIScAddressNotIncluded(boolean val) {
		this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().setSRIScAddressNotIncluded(val);
		this.testerHost.markStore();
	}
	@Override
	public MtFSMReaction getMtFSMReaction() {
		return this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getMtFSMReaction();
	}

	@Override
	public String getMtFSMReaction_Value() {
		return this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getMtFSMReaction().toString();
	}

	@Override
	public void setMtFSMReaction(MtFSMReaction val) {
		this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().setMtFSMReaction(val);
		this.testerHost.markStore();
	}

	@Override
	public void putSRIReaction(String val) {
		SRIReaction x = SRIReaction.createInstance(val);
		if (x != null)
			this.setSRIReaction(x);
	}

	@Override
	public void putSRIInformServiceCenter(String val) {
		SRIInformServiceCenter x = SRIInformServiceCenter.createInstance(val);
		if (x != null)
			this.setSRIInformServiceCenter(x);
	}

	@Override
	public void putMtFSMReaction(String val) {
		MtFSMReaction x = MtFSMReaction.createInstance(val);
		if (x != null)
			this.setMtFSMReaction(x);
	}
	
	@Override
	public String getSRIResponseImsi() {
		return this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getSriResponseImsi();
	}

	@Override
	public void setSRIResponseImsi(String val) {
		this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().setSriResponseImsi(val);
		this.testerHost.markStore();
	}

	@Override
	public String getSRIResponseVlr() {
		return this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getSriResponseVlr();
	}

	@Override
	public void setSRIResponseVlr(String val) {
		this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().setSriResponseVlr(val);
		this.testerHost.markStore();
	}

	@Override
	public int getSmscSsn() {
		return this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getSmscSsn();
	}

	@Override
	public void setSmscSsn(int val) {
		this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().setSmscSsn(val);
		this.testerHost.markStore();
	}

	@Override
	public TypeOfNumberType getTypeOfNumber() {
		return new TypeOfNumberType(this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getTypeOfNumber().getCode());
	}

	@Override
	public String getTypeOfNumber_Value() {
		return new TypeOfNumberType(this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getTypeOfNumber().getCode()).toString();
	}

	@Override
	public void setTypeOfNumber(TypeOfNumberType val) {
		this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().setTypeOfNumber(TypeOfNumber.getInstance(val.intValue()));
		this.testerHost.markStore();
	}

	@Override
	public NumberingPlanIdentificationType getNumberingPlanIdentification() {
		return new NumberingPlanIdentificationType(this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getNumberingPlanIdentification().getCode());
	}

	@Override
	public String getNumberingPlanIdentification_Value() {
		return new NumberingPlanIdentificationType(this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getNumberingPlanIdentification()
				.getCode()).toString();
	}

	@Override
	public void setNumberingPlanIdentification(NumberingPlanIdentificationType val) {
		this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().setNumberingPlanIdentification(NumberingPlanIdentification.getInstance(val.intValue()));
		this.testerHost.markStore();
	}

	@Override
	public SmsCodingType getSmsCodingType() {
		return this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getSmsCodingType();
	}

	@Override
	public String getSmsCodingType_Value() {
		return this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getSmsCodingType().toString();
	}

	@Override
	public void setSmsCodingType(SmsCodingType val) {
		this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().setSmsCodingType(val);
		this.testerHost.markStore();
	}


	@Override
	public void putAddressNature(String val) {
		AddressNatureType x = AddressNatureType.createInstance(val);
		if (x != null)
			this.setAddressNature(x);
	}

	@Override
	public void putNumberingPlan(String val) {
		NumberingPlanMapType x = NumberingPlanMapType.createInstance(val);
		if (x != null)
			this.setNumberingPlan(x);
	}

	@Override
	public void putMapProtocolVersion(String val) {
		MapProtocolVersion x = MapProtocolVersion.createInstance(val);
		if (x != null)
			this.setMapProtocolVersion(x);
	}

	@Override
	public void putTypeOfNumber(String val) {
		TypeOfNumberType x = TypeOfNumberType.createInstance(val);
		if (x != null)
			this.setTypeOfNumber(x);
	}

	@Override
	public void putNumberingPlanIdentification(String val) {
		NumberingPlanIdentificationType x = NumberingPlanIdentificationType.createInstance(val);
		if (x != null)
			this.setNumberingPlanIdentification(x);
	}

	@Override
	public void putSmsCodingType(String val) {
		SmsCodingType x = SmsCodingType.createInstance(val);
		if (x != null)
			this.setSmsCodingType(x);
	}


	@Override
	public String getCurrentRequestDef() {
		return "LastDialog: " + currentRequestDef;
	}

	@Override
	public String getState() {
		StringBuilder sb = new StringBuilder();
		sb.append("<html>");
		sb.append(SOURCE_NAME);
		sb.append(": ");
		sb.append("<br>Count: countSriReq-");
		sb.append(countSriReq);
		sb.append(", countSriResp-");
		sb.append(countSriResp);
		sb.append("<br>countMtFsmReq-");
		sb.append(countMtFsmReq);
		sb.append(", countMtFsmResp-");
		sb.append(countMtFsmResp);
		sb.append("<br> countMoFsmReq-");
		sb.append(countMoFsmReq);
		sb.append(", countMoFsmResp-");
		sb.append(countMoFsmResp);
		sb.append(", countIscReq-");
		sb.append(countIscReq);
		sb.append(", countRsmdsReq-");
		sb.append(countRsmdsReq);
		sb.append(", countRsmdsResp-");
		sb.append(countRsmdsResp);
		sb.append(", countAscReq-");
		sb.append(countAscReq);
		sb.append(", countAscResp-");
		sb.append(countAscResp);
		sb.append(", countErrRcvd-");
		sb.append(countErrRcvd);
		sb.append(", countErrSent-");
		sb.append(countErrSent);
		sb.append("</html>");
		return sb.toString();
	}

	public boolean start() {
		MAPProvider mapProvider = this.mapMan.getMAPStack().getMAPProvider();
		mapProvider.getMAPServiceSms().acivate();
		mapProvider.getMAPServiceSms().addMAPServiceListener(this);
		mapProvider.addMAPDialogListener(this);
		this.testerHost.sendNotif(SOURCE_NAME, "SMS Client has been started", "", Level.INFO);
		isStarted = true;

		return true;
	}

	@Override
	public void stop() {
		MAPProvider mapProvider = this.mapMan.getMAPStack().getMAPProvider();
		isStarted = false;
		mapProvider.getMAPServiceSms().deactivate();
		mapProvider.getMAPServiceSms().removeMAPServiceListener(this);
		mapProvider.removeMAPDialogListener(this);
		this.testerHost.sendNotif(SOURCE_NAME, "SMS Client has been stopped", "", Level.INFO);
	}

	@Override
	public void execute() {
	}


	@Override
	public String closeCurrentDialog() {
		// TODO Auto-generated method stub
		return null;
	}	

	@Override
	public String performMoForwardSM(String msg, String destIsdnNumber, String origIsdnNumber) {
		if (!isStarted)
			return "The tester is not started";
		if (msg == null || msg.equals(""))
			return "Msg is empty";
		if (destIsdnNumber == null || destIsdnNumber.equals(""))
			return "DestIsdnNumber is empty";
		if (origIsdnNumber == null || origIsdnNumber.equals(""))
			return "OrigIsdnNumber is empty";
		int maxMsgLen = this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getSmsCodingType().getSupportesMaxMessageLength();
		if (msg.length() > maxMsgLen)
			return "Simulator does not support message length for current encoding type more than " + maxMsgLen;

		currentRequestDef = "";

		return doMoForwardSM(msg, destIsdnNumber, origIsdnNumber, this.getServiceCenterAddress());
	}

	private String doMoForwardSM(String msg, String destIsdnNumber, String origIsdnNumber, String serviceCentreAddr) {

		MAPProvider mapProvider = this.mapMan.getMAPStack().getMAPProvider();

		MAPApplicationContextVersion vers;
		MAPApplicationContextName acn = MAPApplicationContextName.shortMsgMORelayContext;
		switch (this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getMapProtocolVersion().intValue()) {
		case MapProtocolVersion.VAL_MAP_V1:
			vers = MAPApplicationContextVersion.version1;
			break;
		case MapProtocolVersion.VAL_MAP_V2:
			vers = MAPApplicationContextVersion.version2;
			break;
		default:
			vers = MAPApplicationContextVersion.version3;
			break;
		}
		MAPApplicationContext mapAppContext = MAPApplicationContext.getInstance(acn, vers);

		AddressString serviceCentreAddressDA = mapProvider.getMAPParameterFactory().createAddressString(
				this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getAddressNature(),
				this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getNumberingPlan(), serviceCentreAddr);
		SM_RP_DA da = mapProvider.getMAPParameterFactory().createSM_RP_DA(serviceCentreAddressDA);
		ISDNAddressString msisdn = mapProvider.getMAPParameterFactory().createISDNAddressString(
				this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getAddressNature(),
				this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getNumberingPlan(), origIsdnNumber);
		SM_RP_OA oa = mapProvider.getMAPParameterFactory().createSM_RP_OA_Msisdn(msisdn);

		try {
			AddressField destAddress = new AddressFieldImpl(this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getTypeOfNumber(),
					this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getNumberingPlanIdentification(), destIsdnNumber);
			DataCodingScheme dcs = new DataCodingSchemeImpl(this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getSmsCodingType()
					.intValue() == SmsCodingType.VAL_GSM7 ? 0 : 8);
			UserData userData = new UserDataImpl(msg, dcs, null, null);
			ProtocolIdentifier pi = new ProtocolIdentifierImpl(0);
			ValidityPeriod validityPeriod = new ValidityPeriodImpl(169); // 3
																			// days
			SmsSubmitTpdu tpdu = new SmsSubmitTpduImpl(false, false, false, ++mesRef, destAddress, pi, validityPeriod, userData);
			SmsSignalInfo si = mapProvider.getMAPParameterFactory().createSmsSignalInfo(tpdu, null);

			MAPDialogSms curDialog = mapProvider.getMAPServiceSms().createNewDialog(mapAppContext, this.mapMan.createOrigAddress(), null,
					this.mapMan.createDestAddress(serviceCentreAddr, this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getSmscSsn()),
					null);

			if (si.getData().length < 110 || vers == MAPApplicationContextVersion.version1) {
				if (this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getMapProtocolVersion().intValue() <= 2)
					curDialog.addForwardShortMessageRequest(da, oa, si, false);
				else
					curDialog.addMoForwardShortMessageRequest(da, oa, si, null, null);
				curDialog.send();

				String mtData = createMoData(curDialog.getLocalDialogId(), destIsdnNumber, origIsdnNumber, serviceCentreAddr);
				currentRequestDef += "Sent moReq;";
				this.countMoFsmReq++;
				this.testerHost.sendNotif(SOURCE_NAME, "Sent: moReq: " + msg, mtData, Level.DEBUG);
			} else {
				ResendMessageData md = new ResendMessageData();
				md.da = da;
				md.oa = oa;
				md.si = si;
				md.destIsdnNumber = destIsdnNumber;
				md.origIsdnNumber = origIsdnNumber;
				md.serviceCentreAddr = serviceCentreAddr;
				md.msg = msg;
				curDialog.setUserObject(md);

				curDialog.send();
				currentRequestDef += "Sent emptTBegin;";
				this.testerHost.sendNotif(SOURCE_NAME, "Sent: emptTBegin", "", Level.DEBUG);
			}

			return "MoForwardShortMessageRequest has been sent";
		} catch (MAPException ex) {
			return "Exception when sending MoForwardShortMessageRequest: " + ex.toString();
		}
	}

	private String createMoData(long dialogId, String destIsdnNumber, String origIsdnNumber, String serviceCentreAddr) {
		StringBuilder sb = new StringBuilder();
		sb.append("dialogId=");
		sb.append(dialogId);
		sb.append(", destIsdnNumber=\"");
		sb.append(destIsdnNumber);
		sb.append(", origIsdnNumber=\"");
		sb.append(origIsdnNumber);
		sb.append("\", serviceCentreAddr=\"");
		sb.append(serviceCentreAddr);
		sb.append("\"");
		return sb.toString();
	}

	@Override
	public String performAlertServiceCentre(String destIsdnNumber) {
		if (!isStarted)
			return "The tester is not started";
		if (destIsdnNumber == null || destIsdnNumber.equals(""))
			return "DestIsdnNumber is empty";

		currentRequestDef = "";

		return doAlertServiceCentre(destIsdnNumber, this.getServiceCenterAddress());
	}

	private String doAlertServiceCentre(String destIsdnNumber, String serviceCentreAddr) {

		MAPProvider mapProvider = this.mapMan.getMAPStack().getMAPProvider();

		MAPApplicationContextVersion vers;
		MAPApplicationContextName acn = MAPApplicationContextName.shortMsgAlertContext;
		switch (this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getMapProtocolVersion().intValue()) {
		case MapProtocolVersion.VAL_MAP_V1:
			vers = MAPApplicationContextVersion.version1;
			break;
		default:
			vers = MAPApplicationContextVersion.version2;
			break;
		}
		MAPApplicationContext mapAppContext = MAPApplicationContext.getInstance(acn, vers);

		try {
			ISDNAddressString msisdn = mapProvider.getMAPParameterFactory().createISDNAddressString(
					this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getAddressNature(),
					this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getNumberingPlan(), destIsdnNumber);
			AddressString serviceCentreAddressDA = mapProvider.getMAPParameterFactory().createAddressString(
					this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getAddressNature(),
					this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getNumberingPlan(), serviceCentreAddr);

			MAPDialogSms curDialog = mapProvider.getMAPServiceSms().createNewDialog(mapAppContext, this.mapMan.createOrigAddress(), null,
					this.mapMan.createDestAddress(serviceCentreAddr, this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getSmscSsn()),
					null);

			curDialog.addAlertServiceCentreRequest(msisdn, serviceCentreAddressDA);
			curDialog.send();
			if (vers == MAPApplicationContextVersion.version1)
				curDialog.release();

			String ascData = "isdnNumber=" + destIsdnNumber + ", serviceCentreAddr=" + serviceCentreAddr;
			currentRequestDef += "Sent ascReq;";
			this.countAscReq++;
			this.testerHost.sendNotif(SOURCE_NAME, "Sent: ascReq", ascData, Level.DEBUG);

			return "AlertServiceCentreRequest has been sent";
		} catch (MAPException ex) {
			return "Exception when sending AlertServiceCentreRequest: " + ex.toString();
		}
	}


	@Override
	public void onForwardShortMessageRequest(ForwardShortMessageRequest ind) {
		if (!isStarted)
			return;

		MAPDialogSms curDialog = ind.getMAPDialog();
		long invokeId = ind.getInvokeId();
		SM_RP_DA da = ind.getSM_RP_DA();
		SM_RP_OA oa = ind.getSM_RP_OA();
		SmsSignalInfo si = ind.getSM_RP_UI();

		if (da.getIMSI() != null || da.getLMSI() != null) { // mt message
			this.onMtRequest(da, oa, si, curDialog);

			try {
				if (this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getMtFSMReaction().intValue() == MtFSMReaction.VAL_RETURN_SUCCESS) {
					curDialog.addForwardShortMessageResponse(invokeId);
					this.countMtFsmResp++;
					this.testerHost.sendNotif(SOURCE_NAME, "Sent: mtResp", "", Level.DEBUG);
				} else {
					sendMtError(curDialog, invokeId);
				}

				this.needSendClose = true;

			} catch (MAPException e) {
				this.testerHost.sendNotif(SOURCE_NAME, "Exception when invoking addMtForwardShortMessageResponse : " + e.getMessage(), e, Level.ERROR);
			}
		}
	}

	private void sendMtError(MAPDialogSms curDialog, long invokeId) throws MAPException {
		MAPProvider mapProvider = this.mapMan.getMAPStack().getMAPProvider();
		String uData;
		switch (this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getMtFSMReaction().intValue()) {
		case MtFSMReaction.VAL_ERROR_MEMORY_CAPACITY_EXCEEDED:
		case MtFSMReaction.VAL_ERROR_UNKNOWN_SERVICE_CENTRE:
			SMEnumeratedDeliveryFailureCause smEnumeratedDeliveryFailureCause;
			if (this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getMtFSMReaction().intValue() == MtFSMReaction.VAL_ERROR_MEMORY_CAPACITY_EXCEEDED)
				smEnumeratedDeliveryFailureCause = SMEnumeratedDeliveryFailureCause.memoryCapacityExceeded;
			else
				smEnumeratedDeliveryFailureCause = SMEnumeratedDeliveryFailureCause.unknownServiceCentre;
			MAPErrorMessage mapErrorMessage = mapProvider.getMAPErrorMessageFactory().createMAPErrorMessageSMDeliveryFailure(
					smEnumeratedDeliveryFailureCause, null, null);
			curDialog.sendErrorComponent(invokeId, mapErrorMessage);
			
			this.countErrSent++;
			uData = this.createErrorData(curDialog.getLocalDialogId(), (int)invokeId, mapErrorMessage);
			this.testerHost.sendNotif(SOURCE_NAME, "Sent: errSmDelFail", uData, Level.DEBUG);
			break;
		case MtFSMReaction.VAL_ERROR_ABSENT_SUBSCRIBER:
			mapErrorMessage = null;
			switch (curDialog.getApplicationContext().getApplicationContextVersion()) {
			case version1:
				mapErrorMessage = mapProvider.getMAPErrorMessageFactory().createMAPErrorMessageAbsentSubscriber(null);
				break;
			case version2:
				mapErrorMessage = mapProvider.getMAPErrorMessageFactory().createMAPErrorMessageAbsentSubscriber(null, null);
				break;
			default:
				mapErrorMessage = mapProvider.getMAPErrorMessageFactory().createMAPErrorMessageAbsentSubscriberSM(
						AbsentSubscriberDiagnosticSM.IMSIDetached, null, null);
				break;
			}

			curDialog.sendErrorComponent(invokeId, mapErrorMessage);
			
			this.countErrSent++;
			uData = this.createErrorData(curDialog.getLocalDialogId(), (int)invokeId, mapErrorMessage);
			this.testerHost.sendNotif(SOURCE_NAME, "Sent: errAbsSubs", uData, Level.DEBUG);
			break;
		case MtFSMReaction.VAL_ERROR_SUBSCRIBER_BUSY_FOR_MT_SMS:
			mapErrorMessage = mapProvider.getMAPErrorMessageFactory().createMAPErrorMessageSubscriberBusyForMtSms(null, null);
			curDialog.sendErrorComponent(invokeId, mapErrorMessage);
			
			this.countErrSent++;
			uData = this.createErrorData(curDialog.getLocalDialogId(), (int)invokeId, mapErrorMessage);
			this.testerHost.sendNotif(SOURCE_NAME, "Sent: errSubBusyForMt", uData, Level.DEBUG);
			break;
		case MtFSMReaction.VAL_ERROR_SYSTEM_FAILURE:
			mapErrorMessage = mapProvider.getMAPErrorMessageFactory().createMAPErrorMessageSystemFailure(
					(long) curDialog.getApplicationContext().getApplicationContextVersion().getVersion(), NetworkResource.vmsc, null, null);
			curDialog.sendErrorComponent(invokeId, mapErrorMessage);
			
			this.countErrSent++;
			uData = this.createErrorData(curDialog.getLocalDialogId(), (int)invokeId, mapErrorMessage);
			this.testerHost.sendNotif(SOURCE_NAME, "Sent: errSysFail", uData, Level.DEBUG);
			break;
		}
	}

	private void onMtRequest(SM_RP_DA da, SM_RP_OA oa, SmsSignalInfo si, MAPDialogSms curDialog) {

		this.countMtFsmReq++;

		String destImsi = null;
		if (da != null) {
			IMSI imsi = da.getIMSI();
			if (imsi != null)
				destImsi = imsi.getData();
		}
		AddressString serviceCentreAddr = null;
		
		if (oa != null) {
			serviceCentreAddr = oa.getServiceCentreAddressOA();
		}

		try {
			String msg = null;
			SmsDeliverTpdu dTpdu = null;
			if (si != null) {
				SmsTpdu tpdu = si.decodeTpdu(false);
				if (tpdu instanceof SmsDeliverTpdu) {
					dTpdu = (SmsDeliverTpdu) tpdu;
					UserData ud = dTpdu.getUserData();
					if (ud != null) {
						ud.decode();
						msg = ud.getDecodedMessage();
					}
				}
			}
			String uData = this.createMtData(curDialog, destImsi, dTpdu, serviceCentreAddr);
			this.testerHost.sendNotif(SOURCE_NAME, "Rcvd: mtReq: " + msg, uData, Level.DEBUG);
		} catch (MAPException e) {
			this.testerHost.sendNotif(SOURCE_NAME, "Exception when decoding MtForwardShortMessageRequest tpdu : " + e.getMessage(), e, Level.ERROR);
		}
	}

	@Override
	public void onForwardShortMessageResponse(ForwardShortMessageResponse ind) {
		if (!isStarted)
			return;

		this.countMoFsmResp++;

		MAPDialogSms curDialog = ind.getMAPDialog();
		long invokeId = curDialog.getLocalDialogId();
		currentRequestDef += "Rsvd moResp;";
		this.testerHost.sendNotif(SOURCE_NAME, "Rcvd: moResp", "", Level.DEBUG);
	}

	@Override
	public void onMoForwardShortMessageRequest(MoForwardShortMessageRequest moForwSmInd) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onMoForwardShortMessageResponse(MoForwardShortMessageResponse ind) {
		if (!isStarted)
			return;

		this.countMoFsmResp++;

		MAPDialogSms curDialog = ind.getMAPDialog();
		long invokeId = curDialog.getLocalDialogId();
		currentRequestDef += "Rsvd moResp;";
		this.testerHost.sendNotif(SOURCE_NAME, "Rcvd: moResp", "", Level.DEBUG);
	}

	@Override
	public void onMtForwardShortMessageRequest(MtForwardShortMessageRequest ind) {
		if (!isStarted)
			return;

		MAPDialogSms curDialog = ind.getMAPDialog();
		long invokeId = ind.getInvokeId();
		SM_RP_DA da = ind.getSM_RP_DA();
		SM_RP_OA oa = ind.getSM_RP_OA();
		SmsSignalInfo si = ind.getSM_RP_UI();

		this.onMtRequest(da, oa, si, curDialog);

		try {
			if (this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getMtFSMReaction().intValue() == MtFSMReaction.VAL_RETURN_SUCCESS) {
				curDialog.addMtForwardShortMessageResponse(invokeId, null, null);
				this.countMtFsmResp++;
				this.testerHost.sendNotif(SOURCE_NAME, "Sent: mtResp", "", Level.DEBUG);
			} else {
				sendMtError(curDialog, invokeId);
			}
			
			this.needSendClose = true;

		} catch (MAPException e) {
			this.testerHost.sendNotif(SOURCE_NAME, "Exception when invoking addMtForwardShortMessageResponse : " + e.getMessage(), e, Level.ERROR);
		}		
	}

	private String createMtData(MAPDialogSms dialog, String destImsi, SmsDeliverTpdu dTpdu, AddressString serviceCentreAddr) {
		StringBuilder sb = new StringBuilder();
		sb.append("dialogId=");
		sb.append(dialog.getLocalDialogId());
		sb.append(",\ndestImsi=\"");
		sb.append(destImsi);
		sb.append(",\"\nserviceCentreAddr=\"");
		sb.append(serviceCentreAddr);
		sb.append(",\"\nsmsDeliverTpdu=");
		sb.append(dTpdu);

		sb.append(",\nRemoteAddress=");
		sb.append(dialog.getRemoteAddress());
		sb.append(",\nLocalAddress=");
		sb.append(dialog.getLocalAddress());

		return sb.toString();
	}

	@Override
	public void onMtForwardShortMessageResponse(MtForwardShortMessageResponse mtForwSmRespInd) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onSendRoutingInfoForSMRequest(SendRoutingInfoForSMRequest ind) {
		if (!isStarted)
			return;
		
		this.countSriReq++;

		MAPProvider mapProvider = this.mapMan.getMAPStack().getMAPProvider();
		MAPDialogSms curDialog = ind.getMAPDialog();
		long invokeId = ind.getInvokeId();

		String uData = this.createSriData(ind);
		this.testerHost.sendNotif(SOURCE_NAME, "Rcvd: sriReq", uData, Level.DEBUG);


		IMSI imsi = mapProvider.getMAPParameterFactory().createIMSI(
				this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getSriResponseImsi());
		ISDNAddressString networkNodeNumber = mapProvider.getMAPParameterFactory().createISDNAddressString(
				this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getAddressNature(),
				this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getNumberingPlan(),
				this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getSriResponseVlr());
		LocationInfoWithLMSI li = null;
		boolean informServiceCentrePossible = false;

		try {
			switch (this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getSRIReaction().intValue()) {
			case SRIReaction.VAL_RETURN_SUCCESS:
				li = mapProvider.getMAPParameterFactory().createLocationInfoWithLMSI(networkNodeNumber, null, null, null, null);
				curDialog.addSendRoutingInfoForSMResponse(invokeId, imsi, li, null, null);

				this.countSriResp++;
				uData = this.createSriRespData(curDialog.getLocalDialogId(), imsi, li);
				this.testerHost.sendNotif(SOURCE_NAME, "Sent: sriResp", uData, Level.DEBUG);

				if (curDialog.getApplicationContext().getApplicationContextVersion().getVersion() > 1)
					informServiceCentrePossible = true;
				break;

			case SRIReaction.VAL_RETURN_SUCCESS_WITH_LMSI:
				LMSI lmsi = mapProvider.getMAPParameterFactory().createLMSI(new byte[] { 11, 12, 13, 14 });
				li = mapProvider.getMAPParameterFactory().createLocationInfoWithLMSI(networkNodeNumber, lmsi, null, null, null);
				curDialog.addSendRoutingInfoForSMResponse(invokeId, imsi, li, null, null);

				this.countSriResp++;
				uData = this.createSriRespData(curDialog.getLocalDialogId(), imsi, li);
				this.testerHost.sendNotif(SOURCE_NAME, "Sent: sriResp", uData, Level.DEBUG);

				if (curDialog.getApplicationContext().getApplicationContextVersion().getVersion() > 1)
					informServiceCentrePossible = true;
				break;

			case SRIReaction.VAL_ERROR_ABSENT_SUBSCRIBER:
				MAPErrorMessage mapErrorMessage = null;
				switch (curDialog.getApplicationContext().getApplicationContextVersion()) {
				case version1:
					Boolean mwdSet = null;
					if (this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getSRIInformServiceCenter().intValue() == SRIInformServiceCenter.MWD_mnrf
							|| this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getSRIInformServiceCenter().intValue() == SRIInformServiceCenter.MWD_mcef_mnrf)
						mwdSet = true;
					mapErrorMessage = mapProvider.getMAPErrorMessageFactory().createMAPErrorMessageAbsentSubscriber(mwdSet);
					break;
				case version2:
					mapErrorMessage = mapProvider.getMAPErrorMessageFactory().createMAPErrorMessageAbsentSubscriber(null, null);
					informServiceCentrePossible = true;
					break;
				default:
					mapErrorMessage = mapProvider.getMAPErrorMessageFactory().createMAPErrorMessageAbsentSubscriberSM(
							AbsentSubscriberDiagnosticSM.IMSIDetached, null, null);
					informServiceCentrePossible = true;
					break;
				}

				curDialog.sendErrorComponent(invokeId, mapErrorMessage);
				
				this.countErrSent++;
				uData = this.createErrorData(curDialog.getLocalDialogId(), (int)invokeId, mapErrorMessage);
				this.testerHost.sendNotif(SOURCE_NAME, "Sent: errAbsSubs", uData, Level.DEBUG);
				break;

			case SRIReaction.VAL_ERROR_CALL_BARRED:
				mapErrorMessage = mapProvider.getMAPErrorMessageFactory().createMAPErrorMessageCallBarred(
						(long) curDialog.getApplicationContext().getApplicationContextVersion().getVersion(), CallBarringCause.operatorBarring, null, null);
				curDialog.sendErrorComponent(invokeId, mapErrorMessage);

				this.countErrSent++;
				uData = this.createErrorData(curDialog.getLocalDialogId(), (int)invokeId, mapErrorMessage);
				this.testerHost.sendNotif(SOURCE_NAME, "Sent: errCallBarr", uData, Level.DEBUG);
				break;

			case SRIReaction.VAL_ERROR_SYSTEM_FAILURE:
				mapErrorMessage = mapProvider.getMAPErrorMessageFactory().createMAPErrorMessageSystemFailure(
						(long) curDialog.getApplicationContext().getApplicationContextVersion().getVersion(), NetworkResource.hlr, null, null);
				curDialog.sendErrorComponent(invokeId, mapErrorMessage);
				
				this.countErrSent++;
				uData = this.createErrorData(curDialog.getLocalDialogId(), (int)invokeId, mapErrorMessage);
				this.testerHost.sendNotif(SOURCE_NAME, "Sent: errSysFail", uData, Level.DEBUG);
				break;
			}

			if (informServiceCentrePossible) {
				MWStatus mwStatus = null;
				boolean scAddressNotIncluded = this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().isSRIScAddressNotIncluded();
				switch (this.testerHost.getConfigurationData().getTestSmsClientConfigurationData().getSRIInformServiceCenter().intValue()) {
				case SRIInformServiceCenter.MWD_NO:
					break;
				case SRIInformServiceCenter.MWD_mcef:
					mwStatus = mapProvider.getMAPParameterFactory().createMWStatus(scAddressNotIncluded, false, true, false);
					break;
				case SRIInformServiceCenter.MWD_mnrf:
					mwStatus = mapProvider.getMAPParameterFactory().createMWStatus(scAddressNotIncluded, true, false, false);
					break;
				case SRIInformServiceCenter.MWD_mcef_mnrf:
					mwStatus = mapProvider.getMAPParameterFactory().createMWStatus(scAddressNotIncluded, true, true, false);
					break;
				case SRIInformServiceCenter.MWD_mnrg:
					mwStatus = mapProvider.getMAPParameterFactory().createMWStatus(scAddressNotIncluded, false, false, true);
					break;
				}
				if (mwStatus != null) {
					curDialog.addInformServiceCentreRequest(null, mwStatus, null, null, null);

					this.countIscReq++;
					uData = this.createIscReqData(curDialog.getLocalDialogId(), mwStatus);
					this.testerHost.sendNotif(SOURCE_NAME, "Sent: iscReq", uData, Level.DEBUG);
				}
			}

			this.needSendClose = true;

		} catch (MAPException e) {
			this.testerHost.sendNotif(SOURCE_NAME, "Exception when invoking addSendRoutingInfoForSMResponse() : " + e.getMessage(), e, Level.ERROR);
		}
	}

	private String createSriData(SendRoutingInfoForSMRequest ind) {
		StringBuilder sb = new StringBuilder();
		sb.append("dialogId=");
		sb.append(ind.getMAPDialog().getLocalDialogId());
		sb.append(",\nsriReq=");
		sb.append(ind);

		sb.append(",\nRemoteAddress=");
		sb.append(ind.getMAPDialog().getRemoteAddress());
		sb.append(",\nLocalAddress=");
		sb.append(ind.getMAPDialog().getLocalAddress());

		return sb.toString();
	}

	private String createSriRespData(long dialogId, IMSI imsi, LocationInfoWithLMSI li) {
		StringBuilder sb = new StringBuilder();
		sb.append("dialogId=");
		sb.append(dialogId);
		sb.append(",\n imsi=");
		sb.append(imsi);
		sb.append(",\n locationInfo=");
		sb.append(li);
		sb.append(",\n");
		return sb.toString();
	}

	private String createIscReqData(long dialogId, MWStatus mwStatus) {
		StringBuilder sb = new StringBuilder();
		sb.append("dialogId=");
		sb.append(dialogId);
		sb.append(",\n mwStatus=");
		sb.append(mwStatus);
		sb.append(",\n");
		return sb.toString();
	}

	private String createErrorData(long dialogId, int invokeId, MAPErrorMessage mapErrorMessage) {
		StringBuilder sb = new StringBuilder();
		sb.append("dialogId=");
		sb.append(dialogId);
		sb.append(",\n invokeId=");
		sb.append(invokeId);
		sb.append(",\n mapErrorMessage=");
		sb.append(mapErrorMessage);
		sb.append(",\n");
		return sb.toString();
	}

	@Override
	public void onSendRoutingInfoForSMResponse(SendRoutingInfoForSMResponse sendRoutingInfoForSMRespInd) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onReportSMDeliveryStatusRequest(ReportSMDeliveryStatusRequest ind) {
		if (!isStarted)
			return;

		this.countRsmdsReq++;

		MAPProvider mapProvider = this.mapMan.getMAPStack().getMAPProvider();
		MAPDialogSms curDialog = ind.getMAPDialog();
		long invokeId = ind.getInvokeId();

		this.testerHost.sendNotif(SOURCE_NAME, "Rcvd: rsmdsReq", ind.toString(), Level.DEBUG);

		try {
			curDialog.addReportSMDeliveryStatusResponse(invokeId, null, null);

			this.countRsmdsResp++;
			this.testerHost.sendNotif(SOURCE_NAME, "Sent: rsmdsResp", "", Level.DEBUG);

			this.needSendClose = true;

		} catch (MAPException e) {
			this.testerHost.sendNotif(SOURCE_NAME, "Exception when invoking ReportSMDeliveryStatusResponse : " + e.getMessage(), e, Level.ERROR);
		}
	}

	@Override
	public void onReportSMDeliveryStatusResponse(ReportSMDeliveryStatusResponse reportSMDeliveryStatusRespInd) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onInformServiceCentreRequest(InformServiceCentreRequest informServiceCentreInd) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onAlertServiceCentreRequest(AlertServiceCentreRequest alertServiceCentreInd) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onAlertServiceCentreResponse(AlertServiceCentreResponse ind) {
		if (!isStarted)
			return;

		this.countAscResp++;

		MAPDialogSms curDialog = ind.getMAPDialog();
		long invokeId = curDialog.getLocalDialogId();
		currentRequestDef += "Rsvd ascResp;";
		this.testerHost.sendNotif(SOURCE_NAME, "Rcvd: ascResp", "", Level.DEBUG);
	}

	@Override
	public void onDialogRequest(MAPDialog dlg, AddressString arg1, AddressString arg2, MAPExtensionContainer arg3) {
		// refuse example
//		try {
//			dlg.refuse(Reason.invalidDestinationReference);
//		} catch (MAPException e) {
//			e.printStackTrace();
//		}
	}

	@Override
	public void onDialogDelimiter(MAPDialog mapDialog) {

		if (mapDialog.getApplicationContext().getApplicationContextName() == MAPApplicationContextName.shortMsgMTRelayContext
				|| mapDialog.getApplicationContext().getApplicationContextName() == MAPApplicationContextName.shortMsgMORelayContext) {
			if (mapDialog.getUserObject() != null) {
				ResendMessageData md = (ResendMessageData) mapDialog.getUserObject();
				try {
					MAPDialogSms dlg = (MAPDialogSms) mapDialog;

					if (dlg.getApplicationContext().getApplicationContextVersion().getVersion() <= 2)
						dlg.addForwardShortMessageRequest(md.da, md.oa, md.si, false);
					else
						dlg.addMoForwardShortMessageRequest(md.da, md.oa, md.si, null, null);
					mapDialog.send();

					String mtData = createMoData(mapDialog.getLocalDialogId(), md.destIsdnNumber, md.origIsdnNumber, md.serviceCentreAddr);
					currentRequestDef += "Rcvd emptTCont;Sent moReq;";
					this.countMoFsmReq++;
					this.testerHost.sendNotif(SOURCE_NAME, "Rcvd: emptTCont", "", Level.DEBUG);
					this.testerHost.sendNotif(SOURCE_NAME, "Sent: moReq: " + md.msg, mtData, Level.DEBUG);
				} catch (Exception e) {
					this.testerHost.sendNotif(SOURCE_NAME, "Exception when invoking close() : " + e.getMessage(), e, Level.ERROR);
					return;
				}
				mapDialog.setUserObject(null);
				return;
			}
		}
		
		try {
			if (needSendSend) {
				needSendSend = false;
				mapDialog.send();
				return;
			}
		} catch (Exception e) {
			this.testerHost.sendNotif(SOURCE_NAME, "Exception when invoking send() : " + e.getMessage(), e, Level.ERROR);
			return;
		}
		try {
			if (needSendClose) {
				needSendClose = false;
				mapDialog.close(false);
				return;
			}
		} catch (Exception e) {
			this.testerHost.sendNotif(SOURCE_NAME, "Exception when invoking close() : " + e.getMessage(), e, Level.ERROR);
			return;
		}

		if (mapDialog.getApplicationContext().getApplicationContextName() == MAPApplicationContextName.shortMsgMTRelayContext
				|| mapDialog.getApplicationContext().getApplicationContextName() == MAPApplicationContextName.shortMsgMORelayContext) {
			// this is an empty first TC-BEGIN for MO SMS
			try {
				mapDialog.send();
				currentRequestDef += "Rcvd emptTBeg;Sent emptTCont;";
				this.testerHost.sendNotif(SOURCE_NAME, "Rcvd: emptTBeg", "", Level.DEBUG);
				this.testerHost.sendNotif(SOURCE_NAME, "Sent: emptTCont", "", Level.DEBUG);
			} catch (Exception e) {
				this.testerHost.sendNotif(SOURCE_NAME, "Exception when invoking send() : " + e.getMessage(), e, Level.ERROR);
			}
			return;
		}
	}

	@Override
	public void onErrorComponent(MAPDialog dlg, Long invokeId, MAPErrorMessage msg) {
		super.onErrorComponent(dlg, invokeId, msg);

//		needSendClose = true;
	}

	@Override
	public void onRejectComponent(MAPDialog mapDialog, Long invokeId, Problem problem, boolean isLocalOriginated) {
		super.onRejectComponent(mapDialog, invokeId, problem, isLocalOriginated);
		if (isLocalOriginated)
			needSendClose = true;
	}

	private class ResendMessageData {
		public SM_RP_DA da;
		public SM_RP_OA oa;
		public SmsSignalInfo si;
		public String msg;
		public String destIsdnNumber;
		public String origIsdnNumber;
		public String serviceCentreAddr;
	}
}

